<template>
  <div class="Learning-effectApis">
    <h3>effectScope</h3>
    <p>创建一个 effect 作用域，可以捕获其中所创建的响应式副作用 (即计算属性和侦听器)，这样捕获到的副作用可以一起处理。</p>
    <codeContainer>
      <template #default>
        <div class="flex v h">点击按钮停止控制台的打印和message的更新
          <button @click="stop">scope.stop()</button>
        </div>
        <p>count: {{ count }}</p>
        <p>doubled: {{ doubled }}</p>
        <p>message: {{ message }}</p>
      </template>
      <template #code>
            <pre data-type="js">
              {{ codeFragment["vue-1"] }}
            </pre>
      </template>
    </codeContainer>
    <h3>onScopeDispose</h3>
    <p>在当前活跃的 effect 作用域上注册一个处理回调函数。当相关的 effect 作用域停止时会调用这个回调函数。
      这个方法可以作为可复用的组合式函数中 <code>onUnmounted</code> 的替代品，它并不与组件耦合，因为每一个 Vue 组件的
      <code>setup()</code> 函数也是在一个 effect 作用域中调用的。
    </p>
    <p><code>onScopeDispose</code> 代表一个 effect 作用域的销毁</p>
    <p><code>onUnmounted</code> 代表一个 组件实例的销毁</p>
    <p>在组件内 <code>onScopeDispose</code> 和 <code>onUnmounted</code>功能类似，由于 <code>setup()</code>
      默认会为当前的组件实例创建一个 scope，所以当没有明确声明一个scope的时候，<code>onScopeDispose</code> 等同于 <code>onUnmounted</code>
    </p>
  </div>
</template>

<script setup>
import {
  computed, effectScope, isProxy, onScopeDispose, onUnmounted, ref, watch, watchEffect
} from 'vue';
import CodeContainer from '@/components/codeContainer/codeContainer.vue';
import codeFragment from '../../assets/js/codeFragment';

// codeFragment-split
const count = ref(0);
const message = ref('--');
const timer = setInterval(() => {
  count.value += 1;
}, 1000);
const scope = effectScope();
let doubled;
// 将由 count 引起的副作用全部放入run方法中执行
scope.run(() => {
  doubled = computed(() => count.value * 2);

  watch(count, (val) => message.value = `count changed! ==> ${val}`);

  // 当前 effect 作用域销毁的回调函数
  onScopeDispose(() => {
    console.log('onScopeDispose: 该作用域已销毁!');
  });

  watchEffect(() => console.log(`doubled changed! ==> ${doubled.value}`));
});

function stop() {
  // 处理掉当前作用域内的所有 effect
  scope.stop();
  // doubled 数据类型不变 只是消除依赖不会再更新
  console.log(isProxy(doubled));
}

onScopeDispose(() => {
  clearInterval(timer);
  console.log('onScopeDispose: 该组件销毁了!');
});
onUnmounted(() => {
  console.log('onUnmounted: 该组件销毁了!');
});
</script>

<style scoped lang="scss">
.Learning-effectApis {

}
</style>
